﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using Cowi.ImageManager.WebServices;
using System.Xml;
using System.Xml.Serialization;
using ESRI.ArcGIS.Client;
using ESRI.ArcGIS.Client.Geometry;
using WrapPanel;
using Visifire.Charts;

namespace Silverroute
{
    public partial class MainPage : UserControl
    {
        //Web client for communication with PyramidTileServer
        private System.Net.WebClient tileServerClient = new System.Net.WebClient();
        private string tileServerUrl;
        
        //Web request object
        private object tileServerRequestTypeGetPyramidInfo = new object();

        //The map layer
        private CIMTiledMapServiceLayer baseLayer;

        //List of all the maps the server can supply (we only need one, actor cant choose)
        private List<PyramidInfo> pyramidInfos = new List<PyramidInfo>();

        //View of the city Silkeborg
        private Envelope homeView = new Envelope();
       
        public MainPage()
        {
            tileServerUrl = @"http://dklyimg1/Cowi.ImageManager.WebServices/TileServer.ashx";
            InitializeComponent();

            // Connect map and navigator 
            EsriNavigator.Map = EsriMap;

            // Get list of pyramids from the tile server
            tileServerClient.DownloadStringCompleted += new DownloadStringCompletedEventHandler(tileServerClient_DownloadStringCompleted);
            tileServerClient.DownloadStringAsync(new Uri(tileServerUrl + "?pyramidInfo="), tileServerRequestTypeGetPyramidInfo);

            //Create the envelope for the city Silkeborg
            homeView = new Envelope();
            homeView.XMax = 530165.4356;
            homeView.XMin = 536906.3557;
            homeView.YMax = 6227659.7952;
            homeView.YMin = 6223809.9162;

            //Zoom should be slowed down slightly to give a better "feel".
            EsriMap.ZoomDuration = new TimeSpan(0, 0, 2);
            EsriMap.ZoomFactor = 0.99;
            calculateHeightProfile();
        }

        void calculateHeightProfile()
        {
            chart.Series[0].DataPoints.Add(new Visifire.Charts.DataPoint() { XValue= 1, YValue = 95 });
            chart.Series[0].DataPoints.Add(new Visifire.Charts.DataPoint() { XValue = 2, YValue = 100 });
            chart.Series[0].DataPoints.Add(new Visifire.Charts.DataPoint() { XValue = 3, YValue = 112 });
            chart.Series[0].DataPoints.Add(new Visifire.Charts.DataPoint() { XValue = 4, YValue = 113 });
            chart.Series[0].DataPoints.Add(new Visifire.Charts.DataPoint() { XValue = 5, YValue = 145 });
            chart.Series[0].DataPoints.Add(new Visifire.Charts.DataPoint() { XValue = 6, YValue = 130 });
            chart.Series[0].DataPoints.Add(new Visifire.Charts.DataPoint() { XValue = 7, YValue = 150 });
            chart.Series[0].DataPoints.Add(new Visifire.Charts.DataPoint() { XValue = 8, YValue = 125 });
            chart.Series[0].DataPoints.Add(new Visifire.Charts.DataPoint() { XValue = 9, YValue = 138 });
            chart.Series[0].DataPoints.Add(new Visifire.Charts.DataPoint() { XValue = 10, YValue = 119 });
            chart.Series[0].DataPoints.Add(new Visifire.Charts.DataPoint() { YValue = 100 });
            chart.Series[0].DataPoints.Add(new Visifire.Charts.DataPoint() { YValue = 112 });
            chart.Series[0].DataPoints.Add(new Visifire.Charts.DataPoint() { YValue = 113 });
            chart.Series[0].DataPoints.Add(new Visifire.Charts.DataPoint() { YValue = 145 });
            chart.Series[0].DataPoints.Add(new Visifire.Charts.DataPoint() { YValue = 130 });
            chart.Series[0].DataPoints.Add(new Visifire.Charts.DataPoint() { YValue = 150 });
            chart.Series[0].DataPoints.Add(new Visifire.Charts.DataPoint() { YValue = 125 });
            chart.Series[0].DataPoints.Add(new Visifire.Charts.DataPoint() { YValue = 138 });
            chart.Series[0].DataPoints.Add(new Visifire.Charts.DataPoint() { YValue = 119 });

            //We should count the amount of datapoints in the series and set a specific maximum to avoid chart whitespace.
            chart.AxesX[0].AxisMaximum = chart.Series[0].DataPoints.Count;
        }

        // We got a response from the tile server
        void tileServerClient_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
        {
            // Check if it was a pyramid info request
            if (e.UserState == tileServerRequestTypeGetPyramidInfo)
            {
                try
                {
                    //The response from the tileserver is in XML, we deserialize it into a CTSResponse.
                    XmlSerializer serializer = new XmlSerializer(typeof(CTSResponse));
                    CTSResponse response = (CTSResponse)serializer.Deserialize(new System.IO.MemoryStream(System.Text.Encoding.UTF8.GetBytes(e.Result)));
                    
                    //The response should contain the list of pyramids. Can however be an error.
                    if (response is PyramidInfoResponse)
                    {
                        PyramidInfoResponse pyramidInfoResponse = response as PyramidInfoResponse;

                        // Check if we got any pyramids. List can be (but shouldnt) empty.
                        if (pyramidInfoResponse.PyramidInfos.Count > 0)
                        {
                            // We add the pyramids to our pyramid list.
                            foreach (PyramidInfo pyramidInfo in pyramidInfoResponse.PyramidInfos)
                            {
                                pyramidInfos.Add(pyramidInfo);
                            }
                        }
                    }
                    SetCIMLayers();
                }
                catch
                {

                }
            }
        }

        //COWIs imagemanager layers are different to the ones ESRI reads. We convert them.
        private void SetCIMLayers()
        {
            //Baselayer is set to COWIs DDOLAND2008 map source
            this.baseLayer = new CIMTiledMapServiceLayer(pyramidInfos.ElementAt(1) as PyramidInfo, this.tileServerUrl);
            EsriMap.Layers.Add(baseLayer);

            //The initial view of the city "Silkeborg" is set. We zoom to it to give a "nice" feel.
            EsriMap.ZoomTo(homeView);
            //EsriMap.Extent = homeView;
        }

        //Actor wants to zoom back to Silkeborg.
        private void ToolboxHome_Click(object sender, RoutedEventArgs e)
        {
            //Again instead of hardsetting the extent (instant cross over) we zoom to the envelope
            EsriMap.ZoomTo(homeView); 
        }

        //Actor wants the full view of Denmark.
        private void ToolboxFull_Click(object sender, RoutedEventArgs e)
        {
            //Again instead of hardsetting the extent (instant cross over) we zoom to the envelope
            EsriMap.ZoomTo(baseLayer.FullExtent);
        }

        private void ToolboxHeight_Click(object sender, RoutedEventArgs e)
        {
            Random r = new Random();

            chart.Series[0].DataPoints.Add(new Visifire.Charts.DataPoint() { YValue = r.Next(100, 200)});
            chart.AxesX[0].AxisMaximum = chart.Series[0].DataPoints.Count;
        }

        //We set the variables for the popup dialog box and make it visible.
        private void ToolboxHelp_Click(object sender, RoutedEventArgs e)
        {
            PopupDialogWrapper wrapper = new PopupDialogWrapper();
            wrapper.Title = "Navigations Hjælp";
            wrapper.Description = "Shift+LeftMouse: Firkant der zoomes til. \n" +
                                    "LeftMouse+Drag: Panorer rundt på kortet. \n" +
                                    "Mousewheel up/down: Zoom ind og ud. \n" +
                                    "Piltaster: Panorer på kortet. \n";
            PopupDialog.DataContext = wrapper;
            PopupDialog.Visibility = Visibility.Visible;
            
        }
    }

}
